/**
 *    Copyright 2010 Merrick Zhang ( anphorea@gmail.com )
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 *
 */
package anpho.proxyvalidator.proc;

import java.net.Proxy;
import java.util.Set;

import anpho.proxyvalidator.bean.ProxyBean;
import anpho.proxyvalidator.config.AppContext;

/**
 * @author Merrick
 */
public class ValidatorMgr extends AValidator {
	/**
	 * the default thread count.
	 */
	static int	DEFAULT_THREAD	= AppContext.getInt("DEFAULT_THREAD_COUNT");

	/**
	 * if DEFAULT_THREAD is not set in the settings.properties file,it will be
	 * set to 20 here.
	 */
	public ValidatorMgr() {
		if (DEFAULT_THREAD == 0) {
			DEFAULT_THREAD = 20;
		}
	}

	/**
	 * This is a CallBack method used for the work threads to report the
	 * results.
	 * 
	 * @param pb
	 */
	protected void addResult(ProxyBean pb) {
		if (pb != null) {
			poolOut.add(pb);
		}
	}

	/**
	 * This method is called by the work threads to get a proxy to validate. if
	 * there is no proxy left,return null.
	 * 
	 * @return null if empty,otherwise a proxy.
	 */
	protected Proxy getNextProxy() {
		synchronized (poolIn) {
			if (poolIn.isEmpty())
				// if the work set is empty,return null;
				return null;
			else {
				// get an element then remove it from the set.
				Proxy p = poolIn.iterator().next();
				poolIn.remove(p);
				System.out.println("Processing " + p + " " + poolIn.size() + " left ");
				return p;
			}
		}
	}

	/**
	 * Start up n threads to process.
	 * 
	 * @param n
	 */
	public void start(int n) {
		for (int i = 0; i < n; i++) {
			ValidatorThread t = new ValidatorThread(this);
			Thread tv = new Thread(t);
			vPool.add(tv);
			tv.start();
		}
	}

	/*
	 * (non-Javadoc)
	 * @see anpho.proxyvalidator.proc.AValidator#validate(java.util.Set)
	 */
	@Override
	public void validate(Set<Proxy> p) {
		poolIn.addAll(p);
		start(DEFAULT_THREAD);
	}

	/**
	 * This method is called by the ValidatorThreads when they finished the job
	 * and exit the process.
	 * 
	 * @param t
	 */
	protected void NotifyExit(Thread t) {
		synchronized (vPool) {
			vPool.remove(t);
		}
		if (vPool.isEmpty()) {
			notifyCallBackHanders(poolOut);
		}

	}

}
